package dsk.demo.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dsk.demo.common.utils.PageUtils;
import dsk.demo.common.utils.StreamUtils;
import dsk.demo.product.dao.ProductCarDao;
import dsk.demo.product.dao.ProductDao;
import dsk.demo.product.dao.ProductRefDao;
import dsk.demo.product.dto.ProductQueryDto;
import dsk.demo.product.dto.ProductSaveDto;
import dsk.demo.product.entity.ProductCarEntity;
import dsk.demo.product.entity.ProductEntity;
import dsk.demo.product.entity.ProductRefEntity;
import dsk.demo.product.service.ProductCarService;
import dsk.demo.product.service.ProductRefService;
import dsk.demo.product.service.ProductService;
import dsk.demo.product.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


@Service("productService")
public class ProductServiceImpl extends ServiceImpl<ProductDao, ProductEntity> implements ProductService {

    @Autowired
    ProductDao productDao;

    @Autowired
    ProductRefService productRefService;
    @Autowired
    ProductCarService productCarService;

    @Autowired
    ProductCarDao carDao;
    @Autowired
    ProductRefDao refDao;

    @Override
    public PageUtils queryPage(ProductQueryDto dto) {
        //分页对象
        Page<ProductVo> page = new Page<>(dto.getPage(), dto.getLimit());
        IPage<ProductVo> productListByPage = productDao.getProductListByPage(page, dto);
        PageUtils pageUtils = new PageUtils(productListByPage);
        Integer total = productDao.getCount(dto);
        pageUtils.setTotalCount(total);
        pageUtils.setTotalPage(pageUtils.getTotalCount() / pageUtils.getPageSize() + 1);
        return pageUtils;
    }

    @Override
    public PageUtils queryHoutaiPage(ProductQueryDto dto) {
        //分页对象
        Page<ProductVo> page = new Page<>(dto.getPage(), dto.getLimit());
        IPage<ProductVo> productListByPage = productDao.getProductListByHoutaiPage(page, dto);
        PageUtils pageUtils = new PageUtils(productListByPage);
        Integer total = productDao.getCount(dto);
        pageUtils.setTotalCount(total);
        pageUtils.setTotalPage(pageUtils.getTotalCount() / pageUtils.getPageSize() + 1);
        return pageUtils;
    }

    @Override
    public List<ProductVo> queryRandomList(ProductQueryDto dto) {
        return productDao.getRandomList(dto);
    }

    @Override
    public ProductVo getDetailById(Long id) {
        ProductVo result = productDao.getDetailById(id);
        List<ProductCarEntity> carList = result.getCarList();
        List<ProductCarEntity> newList = new ArrayList<>();

        for (ProductCarEntity entity : carList) {
            if (entity.getId() != null) {
                newList.add(entity);
            }
        }
        result.setCarList(newList);
        return result;
    }

    @Override
    public List<ProductEntity> queryByProductNos(List<String> productNos) {
        QueryWrapper<ProductEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_no", productNos);
        return productDao.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public void saveOrUpdateProduct(ProductSaveDto product) {
        this.saveOrUpdate(product);
        if (CollectionUtil.isNotEmpty(product.getDeleteCarIdList())) {
            productCarService.removeByIds(product.getDeleteCarIdList());
        }
        if (CollectionUtil.isNotEmpty(product.getDeleteOemIdList())) {
            productRefService.removeByIds(product.getDeleteOemIdList());
        }
        List<ProductRefEntity> oemList = product.getOemList();
        productRefService.saveOrUpdateBatch(oemList.stream().collect(Collectors.toSet()));
        List<ProductCarEntity> carList = product.getCarList();
        productCarService.saveOrUpdateBatch(carList.stream().collect(Collectors.toSet()));
    }

    @Override
    @Transactional
    public void saveImage(Long productId, String filePath, Integer type) {
        ProductEntity detailById = (ProductEntity) getDetailById(productId);
        if (detailById != null) {
            switch (type) {
                case 0:
                    detailById.setImage(filePath);
                    break;
                case 1:
                    detailById.setImage1(filePath);
                    break;
                case 2:
                    detailById.setImage2(filePath);
                    break;
                case 3:
                    detailById.setImage3(filePath);
                    break;
                case 4:
                    detailById.setImage4(filePath);
                    break;
                case 5:
                    detailById.setImage5(filePath);
                    break;
            }
            updateById(detailById);
        }
    }

    @Override
    public List<ProductEntity> excel2ProductEntityList(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            Map<String, String> map = new HashMap<>();
            map.put("本厂编号", "productNo");
            map.put("图片地址", "image");
            map.put("价格", "price");
            map.put("价格1", "price1");
            map.put("属性", "attributes");
            map.put("图片1", "image1");
            map.put("图片2", "image2");
            map.put("图片3", "image3");
            map.put("图片4", "image4");
            map.put("图片5", "image5");
            reader.setHeaderAlias(map);
            List<ProductEntity> all = reader.readAll(ProductEntity.class);
            return all;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public Long getMaxId() {
        return productDao.getMaxId();
    }

    @Override
    public Long getIdByProductNo(String productNo) {
        return productDao.getIdByProductNo(productNo);
    }


    /**
     * 查询相似的产品,   当前产品ID开始 往前查询5个 往后查询5个产品
     * 只需查询产品名称, 产品id, 产品属性
     *
     * @param catalogId
     * @param productId
     * @return
     */
    @Override
    public List<ProductEntity> querySimilarProducts(Long catalogId, Long productId) {
        QueryWrapper<ProductEntity> queryBefore = new QueryWrapper<>();
        queryBefore.select("id", "product_no", "attributes", "image")
                .eq("catalog_id", catalogId)
                .gt("id", productId)
                .orderBy(true, true, "id")
                .last("limit 5");
        List<ProductEntity> productBeforeList = this.list(queryBefore);
        QueryWrapper<ProductEntity> queryAfter = new QueryWrapper<>();
        queryAfter.select("id", "product_no", "attributes", "image")
                .eq("catalog_id", catalogId)
                .lt("id", productId)
                .orderBy(true, false, "id")
                .last("limit 5");
        List<ProductEntity> productAfterList = this.list(queryAfter);
        productAfterList.addAll(productBeforeList);
        productAfterList.sort(Comparator.comparingLong(ProductEntity::getId));
        return productAfterList;
    }

    /**
     * 批量修改产品属性
     *
     * @param productEntities
     */
    @Override
    public void updateList(List<ProductEntity> productEntities) {
        Set<String> collect = productEntities.stream().map(ProductEntity::getProductNo).collect(Collectors.toSet());
        List<ProductEntity> productList = list(Wrappers.<ProductEntity>lambdaQuery()
                .in(ProductEntity::getProductNo, collect));
        // 存在的产品集合
        Set<String> exitProductNoList = productList.stream().map(ProductEntity::getProductNo).collect(Collectors.toSet());
        List<ProductEntity> exitProductList = productEntities.stream().filter(item -> exitProductNoList.contains(item.getProductNo())).collect(Collectors.toList());

        this.baseMapper.updateList(exitProductList);
    }

    @Transactional
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        List<ProductEntity> productEntities = this.baseMapper.selectBatchIds(idList);
        if (CollectionUtil.isEmpty(productEntities)) {
            return true;
        }
        List<ProductCarEntity> productCarEntities = carDao.selectList(Wrappers.<ProductCarEntity>lambdaQuery().in(ProductCarEntity::getProductNo, StreamUtils.toSet(productEntities, ProductEntity::getProductNo)));
        if (CollectionUtil.isNotEmpty(productCarEntities)) {
            carDao.deleteBatchIds(StreamUtils.toList(productCarEntities, ProductCarEntity::getId));
        }
        List<ProductRefEntity> productRefEntities = refDao.selectList(Wrappers.<ProductRefEntity>lambdaQuery().in(ProductRefEntity::getProductNo, StreamUtils.toSet(productEntities, ProductEntity::getProductNo)));
        if (CollectionUtil.isNotEmpty(productRefEntities)) {
            refDao.deleteBatchIds(StreamUtils.toList(productRefEntities, ProductRefEntity::getId));
        }
        return super.removeByIds(StreamUtils.toSet(productEntities, ProductEntity::getId));
    }
}
